; 这个并非pmtest7的精简版，因为pmtest7实在不好精简，目前只是想模拟一下获取内存并放在内存中某个位置
; 再看看编译出来的二进制大小，如果还有充足的空间，再把SetupPaging搞进来

; 这里提供2种方法来获取物理内存，并将其放入phy_mem_size
; 一种是于渊老师提供的方式，亦即反复int 15，然后取得详细信息后，遍历取到的数据，将type=1的_dwBaseAddrLow + _dwLengthLow存入phy_mem_size
; 一种是Linus大神在linux早期版本里的搞法，实际也是调用int 15，但是不用反复调用。
; 对比了一下，两种方式获取到的结果略有不同，第一种方式在16M内存时，获取到的物理内存是：01FF0000h，
; 而第二种方式获取到的物理内存是:01F00000h
; 因为如果要打印物理内存，需要引入很多的代码，就没有打印，只能通过调试看到最后结果，这段代码写得十分随意，有兴趣的其他同学可把功能丰富一些

org 0x7c00

jmp LABEL_START


LABEL_START:
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0100h

; 如果需要用第二种方式，把下面这行注释掉就可以了
%define m1 1
%ifdef m1
	mov ebx, 0
	mov di, mem_chk_buf
.loop:
	mov eax, 0E820h
	mov ecx, 20
	mov edx, 0534D4150h
	int 15h
	jc LABEL_MEM_CHK_FAIL
	add di, 20
	inc dword [_mcr_number]
	cmp ebx, 0
	jne .loop
	jmp LABEL_MEM_CHK_OK
LABEL_MEM_CHK_FAIL:
	mov ax, fail_message
	mov bp, ax
	mov cx, length_fail_message
	mov ax, 01301h
	mov bx, 000ch
	mov dl, 0
	int 10h
	jmp $
LABEL_MEM_CHK_OK:
	mov si, mem_chk_buf
	mov ecx, dword [_mcr_number]
.loop:
	mov di, ARD_STRUCT
	mov dx, 5
.loop_inner:
	mov eax, dword [si]
	; 相当于mov [es:di], eax; add di, 4
	stosd
	add si, 4
	dec dx
	cmp dx, 0
	jnz .loop_inner
	
	cmp dword [_dwType], 1
	jne .2
	mov eax, dword [_dwBaseAddrLow]
	add eax, dword [_dwLengthLow]
	cmp eax, [phy_mem_size]
	jb .2
	mov dword [phy_mem_size], eax
.2:
	loop .loop
	
	jmp $
%else
	mov ah, 0x88
	int 15h
	shl eax, 10
	
	mov [phy_mem_size], eax
	jmp $
%endif


data:
	phy_mem_size: dd 0
	mem_chk_buf: times 256 db 0
	_mcr_number: dd 0
	fail_message: db "get memory size failed"
	length_fail_message equ $ - fail_message
	ARD_STRUCT:
		_dwBaseAddrLow: dd 0
		_dwBaseAddrHigh: dd 0
		_dwLengthLow: dd 0
		_dwLengthHigh: dd 0
		_dwType: dd 0
		
times 510 - ($ - $$) db 0
dw 0xaa55